/**
 * 
 */
package enron;

import java.text.DecimalFormat;

import jade.core.Agent;
import jade.core.behaviours.DataStore;
import jade.domain.FIPAAgentManagement.FailureException;
import jade.domain.FIPAAgentManagement.NotUnderstoodException;
import jade.domain.FIPAAgentManagement.RefuseException;
import jade.lang.acl.ACLMessage;
//import jade.lang.acl.MessageTemplate;
//import jade.proto.ContractNetResponder;
import jade.proto.SSIteratedContractNetResponder;

/**
 * @author StarkRG
 *
 */
public class SellEnergyBehaviour extends SSIteratedContractNetResponder {
	private static final long serialVersionUID = -6769195292428241285L;
	Double energyRequired;
	Double proposedPrice;
	
	Long desiredProfitMargin;

	public SellEnergyBehaviour(Agent a, ACLMessage mt) {
		super(a, mt);
	}
	
	public SellEnergyBehaviour(Agent a, ACLMessage mt, DataStore store) {
		super(a, mt, store);
		
	}
	
	
	@Override
	protected ACLMessage handleCfp(ACLMessage cfp) throws NotUnderstoodException, RefuseException {
		//TODO Handle CFP iterations
		Integer iteration = Integer.parseInt(cfp.getUserDefinedParameter("negotiationIteration"));
//		System.out.println("Auction: " + myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + "(Iteration: " + iteration + ")");
		
		ACLMessage reply = null;
		if(iteration == 0) {
			energyRequired = Double.parseDouble(cfp.getContent());

			if(((VendorAgent)myAgent).getEnergyGenerated() < energyRequired){
				reply = cfp.createReply();
				reply.setPerformative(ACLMessage.REFUSE);
				reply.setContent("Sorry, we are currently unable to meet your demand");
//				System.out.println("Auction: " + myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Rejected: Not enough energy.");
			} else {
				proposedPrice = ((VendorAgent)myAgent).getPrice();
//				System.out.println("Auction: ("+myAgent.getLocalName()+") "+cfp.getSender().getLocalName()+" wishes to purchase "+ energyRequired + "kWh.");
				reply = cfp.createReply();
				reply.setPerformative(ACLMessage.PROPOSE);
				reply.setContent(proposedPrice.toString());
				reply.addUserDefinedParameter("negotiationIteration", iteration.toString());
//				System.out.println("Auction: " +myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Negotiation begins at $" + new DecimalFormat("0.00").format(proposedPrice) + "/kWh. (Iteration: "+ iteration +")");
			}
		} else {
			double buyerPrice = Double.parseDouble(cfp.getContent());
			//decrease proposedPrice if the price difference is more than 10 cents, changes made by Edy
			if (proposedPrice - buyerPrice > 0.1){
//				System.out.println("price $" + new DecimalFormat("0.00").format(buyerPrice)   + " is too low" );
				proposedPrice -= (proposedPrice - buyerPrice) / 4.0;
				reply = cfp.createReply();
				reply.setPerformative(ACLMessage.PROPOSE);
				reply.setContent(new DecimalFormat("0.00").format(proposedPrice));
				reply.addUserDefinedParameter("negotiationIteration", iteration.toString());
				
//				System.out.println("Auction: " +myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Negotiation continues with $" + new DecimalFormat("0.00").format(proposedPrice) + "/kWh. (Iteration: "+ iteration +")");	
			}
		}
		return reply;
		
	}
	
	@Override
	protected ACLMessage handleAcceptProposal(ACLMessage cfp, ACLMessage propose, ACLMessage accept) throws FailureException {
		//TODO Raise price if too few iterations
		if(Integer.parseInt(accept.getUserDefinedParameter("negotiationIteration")) < ((Math.log(((VendorAgent)myAgent).getGrid().getSupplierCount())/Math.log(2)) - 2)) {
			//Price is too low
//			System.out.print(myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Price too low, $" + new DecimalFormat("0.00").format(((VendorAgent)myAgent).getPrice()) + "/kWh");
			((VendorAgent)myAgent).setPrice(((VendorAgent)myAgent).getPrice() * 1.10);
//			System.out.println("Auction: " +" is now $" + new DecimalFormat("0.00").format(((VendorAgent)myAgent).getPrice()) + "/kWh.");
		}
		
		((VendorAgent)myAgent).sellEnergy(energyRequired);

//		System.out.println("Auction: " +myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Sold " + energyRequired + "kWh for $" + new DecimalFormat("0.00").format(((Double)(energyRequired * proposedPrice))));
		ACLMessage inform = accept.createReply();
		inform.setPerformative(ACLMessage.INFORM);
		
		inform.addUserDefinedParameter("energy-provided", energyRequired.toString());
		//System.out.println(accept.getUserDefinedParameter("debugging"));
		return inform;	
	}
	
	protected void handleRejectProposal(ACLMessage cfp, ACLMessage propose, ACLMessage reject) {
		//TODO Price is too high, lower expectations
		//  *** This is the interesting part ***
		if(Integer.parseInt(reject.getUserDefinedParameter("negotiationIteration")) < ((Math.log(((VendorAgent)myAgent).getGrid().getSupplierCount())/Math.log(2)) - 2)) {
//			System.out.print(myAgent.getLocalName() + " - " + cfp.getSender().getLocalName() + " Price too high, $" + new DecimalFormat("0.00").format(((VendorAgent)myAgent).getPrice()) + "/kWh");
			((VendorAgent)myAgent).setPrice(((VendorAgent)myAgent).getPrice() * 0.90);
//			System.out.println("Auction: " +" is now $" + new DecimalFormat("0.00").format(((VendorAgent)myAgent).getPrice()) + "/kWh.");
		}
	}
}
